package com.polonium.eclipserunner.webdriver;

import com.polonium.eclipserunner.core.PoloniumTest;
import com.polonium.eclipserunner.core.PoloniumTestRunner;
import com.polonium.eclipserunner.webdriver.annotations.TargetBrowser;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.Description;

import java.lang.reflect.Method;

import static com.polonium.eclipserunner.webdriver.DriverFactory.CURRENT_BROWSER;
import static com.polonium.eclipserunner.webdriver.DriverFactory.TARGET_BROWSERS;

public class PoloniumWebdriverTestRunner extends PoloniumTestRunner{
	private static final String RUNNING_MESSAGE_PREFIX = "Running on: ";

	public PoloniumWebdriverTestRunner(Class<? extends PoloniumTest> testClass) {
		super(testClass);
		setTargetBrowsers(testClass);
		createBrowsersDescription();
	}

	@Override
	protected void runMethods(){
		invokeMethods(BeforeClass.class);
		
		for (Method test : tests) {
			invokeOnTargetBrowsers(test);
		}
		
		invokeMethods(AfterClass.class);
	}
	
	private void createBrowsersDescription() {
		if(TARGET_BROWSERS.length == 0) descriptionBuilder.createDescription(testInstance.getClass(), tests);
		else if(TARGET_BROWSERS.length == 1){
			CURRENT_BROWSER = TARGET_BROWSERS[0];
			descriptionBuilder.createDescription(testInstance.getClass(), tests);
		}
		else{
			CURRENT_BROWSER = TARGET_BROWSERS[0];
			descriptionBuilder.createDescription(testInstance.getClass(), tests, getBrowserInfo());
			
			for(int i=1 ; i<TARGET_BROWSERS.length ; i++){
				CURRENT_BROWSER = TARGET_BROWSERS[i];
				descriptionBuilder.addDescription(testInstance.getClass(), tests, getBrowserInfo());
				
			}
		}
	}
	
	private void invokeOnTargetBrowsers(Method test) {
		int descriptionPosition = tests.indexOf(test);
		Description testDescription = descriptionBuilder.getTestRootDescription(descriptionPosition);
		
		for(int i=0 ; i<TARGET_BROWSERS.length ; i++){
			CURRENT_BROWSER = TARGET_BROWSERS[i];
			
			try{
				testDescription = descriptionBuilder.getTestRootDescription(descriptionPosition);
			} catch(IndexOutOfBoundsException e){
				break;
			}
	
			if (isReadyToRun(test, testDescription)) {
				try {
					// begin test running
					notifier.setStarted(testDescription);
					invokeMethods(Before.class);
	
					// run test on target browsers
					test.invoke(testInstance);
					notifier.setOK(testDescription);
	
				} catch (Exception e) {
					notifier.checkException(testDescription, e, RUNNING_MESSAGE_PREFIX + DriverFactory.CURRENT_BROWSER.name());
				} finally {
					descriptionPosition += tests.size();
					invokeMethods(After.class);
				}
			}
		}
	}
	
	private void setTargetBrowsers(Class<?> testClass) {
		if(testClass.isAnnotationPresent(TargetBrowser.class)){
			TARGET_BROWSERS = testClass.getAnnotation(TargetBrowser.class).value();
		}
		else DriverFactory.setDefaultBrowser();
	}
	
	private String getBrowserInfo() {
		return "{" + RUNNING_MESSAGE_PREFIX + DriverFactory.CURRENT_BROWSER + "}";
	}
}
